use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::{Error, FromRow, Pool, Postgres};
use uuid::Uuid;
use void_log::log_info;

#[derive(Debug, Clone, Serialize, Deserialize, FromRow, Default)]
pub struct SysUser {
    pub id: Option<Uuid>,
    pub create_time: Option<NaiveDateTime>,
    pub update_time: Option<NaiveDateTime>,
    pub password: Option<String>,
    pub code: Option<i64>,
    pub email: Option<String>,
    pub account: Option<String>,
    pub status: Option<i16>,
}

impl SysUser {
    pub async fn select_all(pool: &Pool<Postgres>) -> Result<Vec<SysUser>, Error> {
        let sql = "SELECT * FROM sys_user";
        sqlx::query_as::<_, Self>(sql).fetch_all(pool).await
    }

    pub async fn select(pool: &Pool<Postgres>, id: &Uuid) -> Result<Self, Error> {
        log_info!("按 Id: {id} 查询用户");
        let sql = "SELECT * FROM sys_user where id = $1";
        sqlx::query_as::<_, Self>(sql).bind(id).fetch_one(pool).await
    }

    pub async fn select_account_code(pool: &Pool<Postgres>, username: &str) -> Result<Self, Error> {
        log_info!("按 Name: {username} 查询用户");
        // 分离账户
        let (account, code) = get_account_code(username);
        // 查询账户
        let sql = "select * from sys_user where code = $1 and account = $2";
        sqlx::query_as::<_, Self>(sql).bind(code).bind(account).fetch_one(pool).await
    }

    pub async fn select_group_id(pool: &Pool<Postgres>, group_id: &Uuid) -> Result<Vec<Self>, Error> {
        log_info!("查询群组 {group_id} 的用户");
        let sql = "SELECT a.* FROM sys_user a, sys_user_guild b where a.id = b.user_id and b.guild_id = $1";
        sqlx::query_as::<_, Self>(sql).bind(group_id).fetch_all(pool).await
    }

    pub async fn _select_channel_id(pool: &Pool<Postgres>, channel_id: &Uuid) -> Result<Vec<Self>, Error> {
        log_info!("查询频道 {channel_id} 的用户");
        let sql = "SELECT a.* FROM sys_user a, sys_user_channel b where a.id = b.user_id and b.channel_id = $1";
        sqlx::query_as::<_, Self>(sql).bind(channel_id).fetch_all(pool).await
    }
}

pub(crate) fn get_account_code(username: &str) -> (String, i64) {
    // 分离账户
    let mut account_code = username.split('#');
    let account = account_code.next().unwrap();
    let code = account_code.last().unwrap_or_default().parse::<i64>().unwrap_or_default();
    (account.to_string(), code)
}